﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Web.Routing;
using MvcRags.Core;

namespace MvcRags.Sorting
{
    public static class SortingHelper
    {
        private const string RequestKeySortOrder = "mvcr_sortOrder";
        private const string RequestKeySortField = "mvcr_sortField";

        public static MvcHtmlString SortLinkFor<TModel, TValue>(this HtmlHelper<IEnumerable<TModel>> htmlHelper,  
                                                   Expression<Func<TModel, TValue>> expression,
                                                   object htmlAttributes = null)
        {
            RouteValueDictionary htmlAtts = new RouteValueDictionary(htmlAttributes);
            RouteValueDictionary args = new RouteValueDictionary();

            var memberExpression = expression.Body as MemberExpression;
            if (memberExpression != null)
            {
                string properyName = memberExpression.Member.Name;
                string linkText = htmlHelper.DisplayNameFor(expression).ToString();
                string actionName = htmlHelper.ViewContext.RouteData.GetRequiredString("action");
                string controllerName = htmlHelper.ViewContext.RouteData.GetRequiredString("controller");
                bool sortAsc = htmlHelper.ViewContext.HttpContext.Request.Params[RequestKeySortOrder] != "False";
                string sortField = htmlHelper.ViewContext.HttpContext.Request.Params[RequestKeySortField];

                args.Add(RequestKeySortField, properyName);
                args.Add(RequestKeySortOrder, !sortAsc);

                if (sortField == properyName)
                {
                    string sortingClass = sortAsc ? "sorting-asc" : "sorting-desc";
                    if (htmlAtts.ContainsKey("class"))
                        htmlAtts["class"] = htmlAtts["class"] + " " + sortingClass;
                    else
                        htmlAtts.Add("class", sortingClass);
                }
                return htmlHelper.ActionLinkwParams(linkText, actionName, controllerName, args, htmlAtts);
            }
            throw new ArgumentException();
        }

        public static IOrderedQueryable<TModel> Sort<TModel, TValue>(this Controller controller, IQueryable<TModel> entries, Expression<Func<TModel, TValue>> defaultFieldExpression)
        {
            var memberExpression = defaultFieldExpression.Body as MemberExpression;
            string defaultFieldName = memberExpression != null ? memberExpression.Member.Name : typeof(TModel).GetProperties().First().Name;
                
            bool sortAsc = controller.Request.Params[RequestKeySortOrder] != "False";
            string sortField = controller.Request.Params[RequestKeySortField] ?? defaultFieldName;
            
            IOrderedQueryable<TModel> sortedEntries;

            if (!String.IsNullOrEmpty(sortField))
                sortedEntries = sortAsc ? entries.OrderBy(sortField) : entries.OrderByDescending(sortField);
            else
                sortedEntries = entries.OrderBy(defaultFieldName);

            controller.ViewData[RequestKeySortField] = sortField;
            controller.ViewData[RequestKeySortOrder] = sortAsc;

            return sortedEntries;
        }
    }
}